package com.zrzhen.springbootdemo.controller;

import com.zrzhen.springbootdemo.common.asyn.DeferredResultEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;

import java.util.concurrent.Callable;

/**
 * 官方文档：https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-async
 * DeferredResult和Callable都是为了异步生成返回值提供基本的支持。
 * 简单来说就是一个请求进来，如果你使用了DeferredResult或者Callable，在没有得到返回数据之前，DispatcherServlet和所有Filter就会退出Servlet容器线程，
 * 但响应保持打开状态，一旦返回数据有了，这个DispatcherServlet就会被再次调用并且处理，以异步产生的方式，向请求端返回值。
 * 这么做的好处就是请求不会长时间占用服务连接池，提高服务器的吞吐量。
 */

@RestController
@RequestMapping("/async")
public class AsynController {

    private static final Logger log = LoggerFactory.getLogger(AsynController.class);

    @Autowired
    private DeferredResultEntity deferredResultEntity;

    @GetMapping("/deferred")
    public DeferredResult<Object> testDeferredResult() {
        log.info("主线程开始！");
        DeferredResult<Object> result = new DeferredResult<Object>();
        deferredResultEntity.setResult(result);
        deferredResultEntity.setFlag(true);
        log.info("主线程结束！");
        return result;
    }

    @GetMapping("/quotes")
    public DeferredResult<String> quotes() {
        DeferredResult<String> deferredResult = new DeferredResult<String>();
        // Save the deferredResult somewhere..
        otherThread(deferredResult);
        return deferredResult;
    }

    // From some other thread
    private void otherThread(DeferredResult<String> deferredResult) {
        new Thread("Thread-1") {
            @Override
            public void run() {
                System.out.println("ruanning: " + Thread.currentThread().getName());
                //只有调用了setResult方法才会返回，否则直到超时
                deferredResult.setResult("eeee");
            }
        }.start();

    }

    @RequestMapping("/callable")
    public Callable<String> processUpload(String param) {

        log.info("主线程开始！");

//        return new Callable<String>() {
//            public String call() throws Exception {
//                // ...
//                return "someView"+param;
//            }
//        };

        Callable<String> result = new Callable<String>() {
            @Override
            public String call() throws Exception {
                log.info("副线程开始！");
                Thread.sleep(1000);
                log.info("副线程结束！");
                return "SUCCESS";
            }

        };
        log.info("主线程结束！");
        return result;
    }



}
